package one.bugu.zookeeper.rpc.framework.client.zookeeper;

import one.bugu.zookeeper.rpc.framework.zookeeper.ZooKeeperHelper;
import one.bugu.zookeeper.rpc.framework.zookeeper.ZookeeperConfiguration;
import com.google.gson.Gson;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created with IntelliJ IDEA.
 * User: LangK
 * Created Date 2019/2/14
 * Time: 15:34
 * Description:
 */
public class RegisterCenterInvokerImpl implements IRegisterCenterInvoker {

    private Gson gson = new Gson();

    private ZookeeperConfiguration zookeeperConfiguration;

    private Map<String, List<String>> providerMap;

    private static Logger logger = LoggerFactory.getLogger(RegisterCenterInvokerImpl.class);

    private ZooKeeperHelper zooKeeperHelper;

    public RegisterCenterInvokerImpl(ZookeeperConfiguration zookeeperConfiguration) {
        this.zookeeperConfiguration = zookeeperConfiguration;
    }


    @Override
    public void initProviderMap() {
        zooKeeperHelper = new ZooKeeperHelper(zookeeperConfiguration.getUrl(), new ClientNodeChangeWatcher());
        providerMap = new ConcurrentHashMap<>();
        updateProviderMap();

    }

    @Override
    public void updateProviderMap() {
        synchronized (this){
            providerMap.clear();
            List<String> serverList = zooKeeperHelper.getChildren(zookeeperConfiguration.getPath());
            if (serverList == null || serverList.isEmpty()) {
                return;
            }
            for (String server : serverList) {
                String serverPath = zookeeperConfiguration.getPath() + "/" + server;
                List<String> providerList = zooKeeperHelper.getChildren(serverPath);
                if (providerList!=null&&!providerList.isEmpty()){
                    providerMap.put(server,providerList);
                }
            }
            logger.info("update socket server finish. server list is:{}", gson.toJson(providerMap));
        }
    }

    @Override
    public Map<String, List<String>> getProviderMap() {
        return providerMap;
    }


    class ClientNodeChangeWatcher implements Watcher {

        public void process(WatchedEvent event) {
            if (event.getType() == Event.EventType.NodeChildrenChanged) {
                logger.info("Watch received NodeChildrenChanged event");
                updateProviderMap();
            }
        }
    }
}
